package Leetcode.每日一题;

import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;

/**
 * @Author kirito
 * @Date 2024/1/5 10:43
 * @PackageName:Leetcode.每日一题
 * @ClassName: 队列中可以看到的人数
 * @Description:
 * 有 n 个人排成一个队列，从左到右 编号为 0 到 n - 1 。给你以一个整数数组 heights ，每个整数 互不相同，heights[i] 表示第 i 个人的高度。
 *
 * 一个人能 看到 他右边另一个人的条件是这两人之间的所有人都比他们两人 矮 。
 * 更正式的，第 i 个人能看到第 j 个人的条件是 i < j 且 min(heights[i], heights[j]) > max(heights[i+1], heights[i+2], ..., heights[j-1]) 。
 *
 * 请你返回一个长度为 n 的数组 answer ，其中 answer[i] 是第 i 个人在他右侧队列中能 看到 的 人数 。
 *
 *
 *
 * 示例 1：
 *
 *
 *
 * 输入：heights = [10,6,8,5,11,9]
 *                      2 1 1 0
 * 输出：[3,1,2,1,1,0]
 * 解释：
 * 第 0 个人能看到编号为 1 ，2 和 4 的人。
 * 第 1 个人能看到编号为 2 的人。
 * 第 2 个人能看到编号为 3 和 4 的人。
 * 第 3 个人能看到编号为 4 的人。
 * 第 4 个人能看到编号为 5 的人。
 * 第 5 个人谁也看不到因为他右边没人。
 * 示例 2：
 *
 * 输入：heights = [5,1,2,3,10]
 *                       1 0
 * 输出：[4,1,1,1,0]
 * @Version 1.0
 */
public class 队列中可以看到的人数 {
    public static int[] canSeePersonsCount(int[] heights) {
        int length = heights.length;  // 数组的高度长度
        int[] res = new int[length];  // 结果数组，长度等于输入数组，用于存储每个位置左边比它矮的人数
        Deque<Integer> stack = new ArrayDeque<>();  // 双端队列，用于存储已经遍历过的元素的索引

        // 从数组的最后一个元素开始向第一个元素遍历
        for (int i = length - 1; i >= 0; i--) {
            int h = heights[i];  // 当前遍历到的元素（高度）
            // 当栈不为空，且栈顶元素（对应的高度）小于当前元素的高度时，进行出栈操作
            // 出栈表示栈顶元素右边的所有元素都已经被当前元素“锁定”，即它们都看不到比当前元素更高的元素了
            while (!stack.isEmpty() && stack.peek() < h) {
                stack.pop();  // 出栈
                res[i]++;  // 栈顶元素对应的计数增加
            }
            // 如果栈不为空，说明当前元素能看到栈顶元素，因此栈顶元素对应的计数也需要加一
            if (!stack.isEmpty()) {
                res[i]++;
            }
            // 将当前元素的索引入栈
            stack.push(h);
        }

        // 返回结果数组
        return res;
    }

    public static void main(String[] args) {
        int[] heights = {10, 6, 8, 5, 11, 9};
        int[] ints = canSeePersonsCount(heights);
        System.out.println(Arrays.toString(ints));
    }
}
